from rest_framework.generics import ListAPIView
from rest_framework.generics import RetrieveAPIView
from rest_framework.generics import CreateAPIView
from rest_framework.exceptions import ValidationError
from rest_framework.filters import BaseFilterBackend
from rest_framework import serializers
from rest_framework.filters import BaseFilterBackend
from rest_framework.pagination import LimitOffsetPagination
from django.forms import model_to_dict
from django.db.models import Max
from api.utils.auth import UserAuthentication
from api import models

class AuctionBaseFilterBackend(BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        max=request.query_params.get('max',None)
        if max:
            return queryset.filter(id__gt=max)
        else:
            return queryset
class AuctionLimitOffsetPagination(LimitOffsetPagination):
    default_limit = 5
    max_limit = 50
    def get_offset(self, request):
        return 0

class AuctionSerializer(serializers.ModelSerializer):


    status=serializers.CharField(source='get_status_display')
    preview_start_time=serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    goods=serializers.SerializerMethodField()

    class Meta:
        model=models.Auction
        fields=['id','status','title','cover','preview_start_time','look_count',
                'goods_count','total_price','bid_count','goods']
    def get_goods(self,obj):
        queryset=models.AuctionItem.objects.filter(auction=obj)[0:5]

        return [item.title for item in queryset]

class AuctionListView(ListAPIView):
    '''
    拍卖专场接口
    '''
    queryset = models.Auction.objects.filter()
    serializer_class = AuctionSerializer
    filter_backends = [AuctionBaseFilterBackend,]
    pagination_class = AuctionLimitOffsetPagination

class AuctionDetailItemSerializer(serializers.ModelSerializer):
    '''
    专场详情页 中的  单品的 信息
    '''
    status=serializers.CharField(source='get_status_display')
    is_deposit=serializers.SerializerMethodField()
    class Meta:
        model=models.AuctionItem
        fields='__all__'

    def get_is_deposit(self,obj):
        print(self.context)
        user=self.context['request'].user

        if not user:
            return False
        print(obj.auction.pk)
        exists=models.DepositRecord.objects.filter(auction=obj.auction,status=2,deposit_type=1).exists()
        if exists:
            return True
        else:
            return False
class AuctionDetailSerializer(serializers.ModelSerializer):
    '''
    专场详情的序列化
    '''
    #商品
    goods=serializers.SerializerMethodField()
    #是否交了专场保证金
    is_deposit=serializers.SerializerMethodField()

    class Meta:
        model=models.Auction
        fields = '__all__'

    def get_goods(self,obj):
        '''
        获取专场的商品信息
        :param obj:
        :return:
        '''
        auc_item=models.AuctionItem.objects.filter(auction=obj)

        ser=AuctionDetailItemSerializer(instance=auc_item,many=True,context=self.context    )
        return ser.data
    def get_is_deposit(self, obj):
        '''
        获取是否交了专场保证金
        :param obj:
        :return:
        '''
        user=self.context['request'].user
        if not user:
            return False
        exists=models.DepositRecord.objects.filter(auction=obj,user=user,status=2,deposit_type=2).exists()
        if exists:
            return True
        else:
            return False
class AuctionDetailView(RetrieveAPIView):
    '''
    专场详细
    '''
    queryset = models.Auction.objects
    serializer_class = AuctionDetailSerializer

class AuctionItemDetailSerializer(serializers.ModelSerializer):
    '''
    拍卖单品详情序列化
    '''
    carousel_list=serializers.SerializerMethodField()
    detail_list=serializers.SerializerMethodField()
    image_list=serializers.SerializerMethodField()
    record=serializers.SerializerMethodField()

    class Meta:
        model=models.AuctionItem
        fields='__all__'
    def get_carousel_list(self,obj):
        queryset = models.AuctionItemImage.objects.filter(item=obj,carousel=True).order_by('order')
        return [str(item.img) for item in queryset]
    def get_detail_list(self, obj):
        queryset=models.AuctionItemDetail.objects.filter(item=obj)
        return [model_to_dict(item,['key','value']) for item in queryset]
    def get_image_list(self, obj):
        queryset=models.AuctionItemImage.objects.filter(item=obj).order_by('order')
        return [str(item.img) for item in queryset]
    def get_record(self,obj):
        queryset=models.BrowseRecord.objects.filter(item=obj)
        result={
            'count':queryset.count(),
            'record':[item.user.avatar for item in queryset[:10]]
        }
        return result
class AuctionItemDetailView(RetrieveAPIView):
    '''
    拍卖单品详情
    '''
    queryset = models.AuctionItem.objects
    serializer_class = AuctionItemDetailSerializer

class AuctionItemDepositModelSerializer(serializers.ModelSerializer):
    '''
    保证金序列化
    '''
    deposit=serializers.SerializerMethodField()
    balance = serializers.SerializerMethodField()
    class Meta:
        model=models.AuctionItem
        fields=['id','title','cover','reserve_price','highest_price','deposit','balance']
    def get_deposit(self,obj):
        result={

            'data_list':[
                {'id': 1, 'title': '全场保证金', 'price': obj.deposit,'selected':True},
                {'id': 2, 'title': '单品保证金', 'price': obj.auction.deposit},
            ]
        }
        return result
    def get_balance(self, obj):

        user=self.context['request'].user

        return user.balance
class AuctionItemDepositView(RetrieveAPIView,CreateAPIView):
    '''
    拍品的保证金
    '''
    queryset = models.AuctionItem.objects
    authentication_classes = [UserAuthentication,]

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return AuctionItemDepositModelSerializer

class BidFilterBackend(BaseFilterBackend):
    '''
    竞价的请求参数的处理
    '''
    def filter_queryset(self, request, queryset, view):
        item_id=request.query_params.get('item_id')
        if item_id:
            return queryset.filter(item_id=item_id)
        else:
            return queryset
class BidModelSerializer(serializers.ModelSerializer):
    '''
    竞价记录的序列化
    '''
    status_text=serializers.CharField(source='get_status_display',read_only=True)
    user_nickname=serializers.CharField(source='user.nickname',read_only=True)
    class Meta:
        model=models.BidRecord
        fields=['item','status_text','user_nickname','price']
    def validate_item(self,item):
        '''
        校验item 必须是在拍卖中
        '''

        exists=models.AuctionItem.objects.filter(pk=item.pk,status=3).exists()
        if not exists:
            raise ValidationError('拍品不在拍卖中！')
        else:
            return item
    def validate_price(self,price):
        '''
        验证出价是否大于最高价
        :param price:
        :return:
        '''

        item_id=self.initial_data.get('item')
        max_price = models.BidRecord.objects.filter(item_id=item_id).aggregate(max=Max('price')).get('max')
        auction_item=models.AuctionItem.objects.filter(pk=item_id).values('start_price','unit').first()
        unit=auction_item.get('unit')
        start_price=auction_item.get('start_price')

        if max_price:

           if price>max_price and (price-max_price)%unit == 0:

               return price
           else:
               raise ValidationError('出价错误')
        else:
            if price>start_price and (price-start_price)%unit == 0:
                return price
            else:
                raise ValidationError('出价错误')
class BidApiView(ListAPIView,CreateAPIView):
    '''
    竞价的展示视图
    '''
    queryset = models.BidRecord.objects

    authentication_classes = [UserAuthentication,]


    def get_queryset(self):

        item_id=self.request.query_params.get('item_id')
        return self.queryset.filter(item_id=item_id)

    def get(self,request,*args,**kwargs):

        response=super().get(request,*args,**kwargs)
        item_id=request.query_params.get('item_id')
        auction_item=models.AuctionItem.objects.filter(pk=item_id).first()

        max_price=models.BidRecord.objects.filter(item_id=item_id).aggregate(max=Max('price')).get('max')

        result={
            'unit':auction_item.unit,
            'price':max_price or auction_item.start_price,
            'bid_list':response.data
        }
        response.data=result
        return response

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return BidModelSerializer
        if self.request.method == 'POST':
            return BidModelSerializer

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)